package com.basic.backend.service.impl;

import com.basic.backend.mapper.AnalysisResultMapper;
import com.basic.backend.model.dto.analysis.AnalysisResponse;
import com.basic.backend.model.entity.AnalysisResult;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Slf4j
@Service
public class AnalysisResultService {

    @Resource
    private AnalysisResultMapper analysisResultMapper;

    @Resource
    private ObjectMapper objectMapper;

    /**
     * 幂等性保存方法：存在则更新，不存在则插入
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveResult(Long articleId, AnalysisResponse response) {
        if (articleId == null || response == null) {
            log.error("参数异常: articleId={}, response={}", articleId, response);
            throw new IllegalArgumentException("参数不能为空");
        }

        // 1. 先尝试查询是否存在记录
        AnalysisResult existingResult = analysisResultMapper.selectByArticleId(articleId);

        if (existingResult != null) {
            // 2. 存在则更新
            updateExistingResult(existingResult, response);
        } else {
            // 3. 不存在则插入（捕获可能的并发插入冲突）
            try {
                insertNewResult(articleId, response);
            } catch (DuplicateKeyException e) {
                log.warn("并发插入冲突，转为更新 articleId={}", articleId);
                updateExistingResult(analysisResultMapper.selectByArticleId(articleId), response);
            }
        }
    }

    /**
     * 插入新记录
     */
    private void insertNewResult(Long articleId, AnalysisResponse response) {
        AnalysisResult newResult = buildAnalysisResult(articleId, response);
        int affectedRows = analysisResultMapper.insert(newResult);
        if (affectedRows != 1) {
            throw new RuntimeException("插入分析结果失败");
        }
        log.info("插入分析结果成功 articleId={}", articleId);
    }

    /**
     * 更新已有记录
     */
    private void updateExistingResult(AnalysisResult existingResult, AnalysisResponse response) {
        AnalysisResult updatedResult = buildAnalysisResult(existingResult.getArticleId(), response);
        updatedResult.setAnalysisId(existingResult.getAnalysisId()); // 保留原主键

        int affectedRows = analysisResultMapper.updateByArticleId(updatedResult);
        if (affectedRows != 1) {
            throw new RuntimeException("更新分析结果失败");
        }
        log.info("更新分析结果成功 articleId={}", existingResult.getArticleId());
    }

    /**
     * 构建实体对象
     */
    private AnalysisResult buildAnalysisResult(Long articleId, AnalysisResponse response) {
        return AnalysisResult.builder()
                .articleId(articleId)
                .authenticityProbability(toPercentage(response.getAuthenticity()))
                .aiProbability(toPercentage(response.getAiProbability()))
                .hotWords(convertHotWordsSafe(response.getHotWords()))
                .analyzedAt(new java.util.Date())
                .aiAnalysisSummary(response.getAiAnalysisSummary())
                .aiReasoning(response.getAiReasoning())
                .model("v1.0")
                .build();
    }

    /**
     * 安全转换概率值
     */
    private BigDecimal toPercentage(Double value) {
        return Optional.ofNullable(value)
                .map(v -> BigDecimal.valueOf(v * 100).setScale(2, RoundingMode.HALF_UP))
                .orElse(BigDecimal.ZERO);
    }

    /**
     * 安全转换热词列表
     */
    private String convertHotWordsSafe(List<AnalysisResponse.HotWord> hotWords) {
        try {
            return objectMapper.writeValueAsString(
                    Optional.ofNullable(hotWords).orElse(Collections.emptyList())
            );
        } catch (JsonProcessingException e) {
            log.error("热词序列化失败", e);
            return "[]";
        }
    }
}